/*
 * DefaultRegister.java   2008/07/28
 *
 * Copyright 2008 Web & Zen Multimedia, All rights reserved.
 * Use is subject to license terms.
 */
package it.wzm.lightweightlog;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Properties;

/**
 * Default implementation of Register, it simply extends Register and store passed Dumper
 * into an ArrayList, called slot.
 */
class DefaultRegister<T extends Dumper> extends Register<T> implements Serializable {

	/**
     * As required by serialization
     */
	private static final long serialVersionUID = -1107606779436763082L;
    /**
     * Where all the Dumper are stored
     */
    private LinkedList<T> slot;

    /**
     * Create register from a given Array of Dumper, null array cause ObjectInitializationException.
     * If in the passed array some Dumper index is null.
     * @param t Array of dumper
     */
    public DefaultRegister(Properties p, ArrayList<T> t) {
        // doing our Duty...
        super(p, t);
    }
    
    @Override
    final void preinit() {
    	// this where our Dumper will be saved...
    	this.slot = new LinkedList<T>();
    }

    
    /**
     * Save a passed Dumper into the slot, if the slot already contains this Dumper,
     * then nothing is stored and false is returned.
     * @param t Anything extending Dumper
     * @return true if Dumper is properly added false if not
     */
    boolean save(T t) {
        return slot.add(t);
    }

    /**
     * Remove a passed Dumper from the slot, if the slot already does not contains this Dumper,
     * or the Dumper status is not FAILURE then nothing is removed and false is returned.
     * @param t Anything extending Dumper
     * @return true if Dumper is properly added false if not
     */
    boolean remove(T t) {
        // easy check...
        if (!slot.contains(t)) {
            return false;
        // only Dumper with status FAILURE can be removed
        }
        if (t.getStatus() == Dumper.Status.FAILURE) {
            return slot.remove(t);
        } else {
            return false;
        }
    }

    /**
     * The size of the slot
     * @return int
     */
    int size() {
        return slot.size();
    }

    /**
     * Dispatch entries to each Dumper in slot
     * @param ll A LinkedList of Entry
     */
    <E extends Entry> void dispatchToDumper(LinkedList<E> ll) {

        // browse each Dumper
        dumping:
        for (T t:slot) {
            // get status...if 'failure' we kill remove from register
            if (t.getStatus() == Dumper.Status.FAILURE) {            	
            	if (t.hasKillOnFailure()) {
            		t.kill();
            		this.remove(t);
            		// no need to continue...
            		// pass to next Dumper
            		continue dumping;
            	}
        	}

            try {
                // opening            	
            	t.open();
                // browse each Entry in list  
                for (Entry e: ll) {
                    t.dump(e);
                }                
                // finally closing...
                t.close();
                
            } catch (DumperException ex) {
            	logger.error(ex);
            	//ex.printStackTrace();
            	//LogFactory.getLog().error(ex);
                if (t.hasKillOnFailure()) {
                	t.kill();
                } else {
                    continue dumping;
                }
            }
            // we don't nedd the list anymore...
            //ll.clear();
        }
    }

    /**
     * Dispatch a single Entry to all Dumper in the slot
     * @param e Anything extending Entry
     */
    <E extends Entry> void dispatchToDumper(E e) {
        // browse each Dumper
        for (T t: slot) {
            try {                
                // the following is normal routine
                t.open();
                t.dump(e);
                t.close();
            } catch (DumperException ex) {
            	ex.printStackTrace();
                //LogFactory.getLog().error(ex);
            	//logger.error(ex);
            }
        }
    }

    /**
     * Close this Register and all Dumper in it 
     */
    @Override
    void shutdown() {    	
        // browse each Dumper
        for (T t: slot) {
            //try {
                t.kill();
                this.remove(t);
            //} catch (DumperException ex) {
            //	LogFactory.getLog().error(ex);
            //}
        }
    }
    
}
